package io.github.eric.urpc.server.handler;

import io.github.eric.urpc.core.conn.Connection;
import io.github.eric.urpc.server.ServerContext;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

@Sharable
public class ServerConnectionHandler extends ServerBaseHandler {

	public ServerConnectionHandler(ServerBootstrap serverBootstrap, ServerContext serverContext) {
		super(serverBootstrap, serverContext);
	}

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) {
        if (serverContext.getLogger().isDebugEnabled()) {
            serverContext.getLogger().debug("[urpc server] channel {} is registered, local addr {}, remote addr {}",
                    ctx.channel().id().asShortText(), ctx.channel().localAddress(), ctx.channel().remoteAddress());
        }
        Connection conn = new Connection(ctx.channel(), serverContext);
        ctx.channel().attr(Connection.TCP).set(conn);
    }

    @Override
    public void channelActive(final ChannelHandlerContext ctx) {
        if (serverContext.getLogger().isDebugEnabled()) {
            serverContext.getLogger().debug("[urpc server] channel {} is active, local addr {}, remote addr {}",
                    ctx.channel().id().asShortText(), ctx.channel().localAddress(), ctx.channel().remoteAddress());
        }
        ctx.channel().attr(Connection.TCP).get().onAccepted();
    }

    //对端主动调用close，都只会触发Inactive，不会导致抛异常
    @Override
    public void channelInactive(final ChannelHandlerContext ctx) {
        if (serverContext.getLogger().isDebugEnabled()) {
            serverContext.getLogger().debug("[urpc server] channel {} is inactive, local addr {}, remote addr {}",
                    ctx.channel().id().asShortText(), ctx.channel().localAddress(), ctx.channel().remoteAddress());
        }
        ctx.channel().attr(Connection.TCP).get().onDisconnected();
        ctx.close();
    }

	@Override
	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.READER_IDLE) {
                ctx.close();
                serverContext.getLogger().info("[urpc server] channel {} read idle, urpc server close it, remote addr {}",
                        ctx.channel().id().asShortText(), ctx.channel().remoteAddress());
            }
        } else {
            ctx.fireUserEventTriggered(evt);
        }
	}

    //对端被动关闭连接（如关闭进程），则先抛出异常，而后触发Inactive
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        serverContext.getLogger().error("[urpc server] channel {} exception caught, local addr {}, remote addr {}",
                ctx.channel().id().asShortText(), ctx.channel().localAddress(), ctx.channel().remoteAddress(), cause);
        ctx.close();
    }


}
